package com.qq5194102.chaindestroy;
import org.bukkit.ChatColor;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;

import java.util.*;

/**
 * @Author caiyh
 * @Date 2025/7/27 1:35
 * @Description
 */
public class TreeFellerListener implements Listener {
    private final ChainDestroy.PluginConfig config;
    private final JavaPlugin plugin;

    // 支持的原木类型 (1.12.2版本)
    private final Set<Material> SUPPORTED_LOGS = EnumSet.of(
            Material.LOG,
            Material.LOG_2
    );

    public TreeFellerListener(JavaPlugin plugin, ChainDestroy.PluginConfig config) {
        this.plugin = plugin;
        this.config = config;
    }

    /**
     * 处理方块破坏事件
     * @param event 方块破坏事件
     */
    @EventHandler
    public void onBlockBreak(BlockBreakEvent event) {
        // 验证前置条件是否满足
        if (!validatePreconditions(event)) return;

        Player player = event.getPlayer();
        Block startBlock = event.getBlock();
        ItemStack tool = player.getInventory().getItemInMainHand();

        // 执行连锁砍树
        int logsChopped = chopConnectedLogs(startBlock, player, tool, config.MAX_TREE_BLOCKS);

        // 玩家反馈
        if (logsChopped > 1) {
            player.sendMessage(ChatColor.GREEN + "连锁砍树触发! 破坏了 " + logsChopped + " 个原木");
        }
    }

    /**
     * 验证连锁砍树的触发条件
     * @param event 方块破坏事件
     * @return 是否满足触发条件
     */
    private boolean validatePreconditions(BlockBreakEvent event) {
        Player player = event.getPlayer();
        Block block = event.getBlock();
        ItemStack tool = player.getInventory().getItemInMainHand();

        // 检查游戏模式和基础条件
        if (player.getGameMode() == GameMode.CREATIVE) return false;
        if (config.REQUIRE_SNEAKING && !player.isSneaking()) return false;
        if (!tool.getType().name().endsWith("_AXE")) return false;
        if (!SUPPORTED_LOGS.contains(block.getType())) return false;
        if (!player.hasPermission("chaindestroy.treefeller")) return false;

        return true;
    }

    /**
     * 砍伐相连的同种原木
     * @param startBlock 起始方块
     * @param player 玩家
     * @param tool 工具
     * @param maxBlocks 最大连锁数
     * @return 实际砍伐的原木数量
     */
    private int chopConnectedLogs(Block startBlock, Player player, ItemStack tool, int maxBlocks) {
        Material targetType = startBlock.getType();
        Queue<Block> queue = new LinkedList<>();
        Set<Block> choppedBlocks = new HashSet<>();

        // 初始化队列
        queue.add(startBlock);
        choppedBlocks.add(startBlock);

        int count = 0;
        while (!queue.isEmpty() && count < maxBlocks) {
            Block current = queue.poll();

            // 只处理目标类型的原木
            if (isValidLogBlock(current, targetType)) {
                // 安全破坏原木
                if (breakBlockSafely(current, player, tool)) {
                    count++;

                    // 工具耐久检查
                    if (isToolBroken(tool)) break;

                    // 添加相连原木到队列
                    addAdjacentLogs(current, queue, choppedBlocks, targetType);
                }
            }
        }

        return count;
    }

    /**
     * 添加相邻的原木到搜索队列（仅限原木）
     * @param block 中心方块
     * @param queue 方块队列
     * @param visited 已访问方块集合
     * @param logType 原木类型
     */
    private void addAdjacentLogs(Block block, Queue<Block> queue, Set<Block> visited, Material logType) {
        // 定义3x3x3搜索范围
        for (int x = -1; x <= 1; x++) {
            for (int y = -1; y <= 1; y++) {
                for (int z = -1; z <= 1; z++) {
                    // 跳过中心自身
                    if (x == 0 && y == 0 && z == 0) continue;

                    Block relative = block.getRelative(x, y, z);
                    if (!visited.contains(relative) &&
                            SUPPORTED_LOGS.contains(relative.getType()) &&
                            relative.getType() == logType) {
                        visited.add(relative);
                        queue.add(relative);
                    }
                }
            }
        }
    }

    /**
     * 检查方块是否为有效的原木类型
     * @param block 方块
     * @param targetType 原木类型
     * @return 是否有效
     */
    private boolean isValidLogBlock(Block block, Material targetType) {
        return block.getType() == targetType;
    }

    /**
     * 安全破坏原木
     * @param block 原木方块
     * @param player 玩家
     * @param tool 工具
     * @return 是否成功破坏
     */
    private boolean breakBlockSafely(Block block, Player player, ItemStack tool) {
        // 跳过无效方块
        if (block.isEmpty() || block.getType() == Material.BEDROCK) return false;

        // 使用原版方法破坏方块（掉落处理）
        block.breakNaturally(tool);

        // 增加工具耐久消耗（固定1点，不加倍）
        if (hasDurability(tool)) {
            short newDurability = (short) (tool.getDurability() + 1);
            tool.setDurability(newDurability);
        }

        return true;
    }

    /**
     * 检查工具是否具有耐久属性
     * @param tool 工具
     * @return 是否有耐久
     */
    private boolean hasDurability(ItemStack tool) {
        return tool.getType().getMaxDurability() > 0;
    }

    /**
     * 检查工具是否损坏
     * @param tool 工具
     * @return 是否损坏
     */
    private boolean isToolBroken(ItemStack tool) {
        return hasDurability(tool) && tool.getDurability() >= tool.getType().getMaxDurability();
    }
}
